//////////////////////////////////////
// Fast Container Library           //
// MIT License - Copyright (c) 2012 //
//////////////////////////////////////

#pragma once

#include "vector.h"
#include "fixed_allocator.h"


FC_NAMESPACE_BEGIN


template <class T, size_t N, class Allocator>
class fixed_vector : public vector<T, Allocator>
{
public:
	typedef fixed_vector<T, N, Allocator>				this_type;
	typedef vector<T, Allocator>						base_type;
	typedef typename base_type::pointer					pointer;
	typedef typename base_type::size_type				size_type;

	using base_type::m_allocator;
	using base_type::m_begin;
	using base_type::m_end;
	using base_type::m_capacity;

	enum
	{
		buffer_size_n_bytes = N * sizeof(T),
		buffer_alignment = FC_ALIGNOF(T)
	};

	typedef aligned_buffer<buffer_size_n_bytes, buffer_alignment> buffer_type;

	fixed_vector()
		: base_type()
		{
			init();
		}

	explicit fixed_vector( size_t n, const T& value = T() )
		: base_type()
		{
			init();
			base_type::InitializeValues( n, value );
		}

	template<class InputIterator>
		fixed_vector( InputIterator first, InputIterator last )
		: base_type()
		{
			init();
			base_type::InitializeIterator( fc::distance(first, last), first, last );
		}

	fixed_vector( const this_type& x )
		: base_type()
		{
			init();
			base_type::InitializeIterator( x.size(), x.begin(), x.end() );
		}

	fixed_vector( const base_type& x )
		: base_type()
		{
			init();
			base_type::InitializeIterator( x.size(), x.begin(), x.end() );
		}

	bool has_overflowed() const
	{
		return m_begin != get_buffer();
	}

	void reset()
	{
		if( m_capacity )
		{
			base_type::clear();
			base_type::deallocate();
		}

		init();
	}

	void init()
	{
		m_begin = m_end = (T*)m_buffer.data;
		m_capacity = m_begin + N;
		m_allocator.set_buffer(m_begin);
	}

	T* get_buffer() const
	{
		return (T*)m_buffer.data;
	}

protected:
	buffer_type m_buffer;

};



FC_NAMESPACE_END
